﻿using System;
using System.Collections.Generic;
using System.Configuration;

using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using System.Collections.ObjectModel;

namespace mvcForum.Tests.WebUI {

	public static class IWebDriverExtensions {

		public static String GetTextBoxValueById(this IWebDriver driver, String id) {
			IWebElement box = driver.FindElement(By.Id(id));
			if (box == null) {
				throw new ApplicationException(String.Format("No element found with the id '{0}'", id));
			}
			return box.GetAttribute("value");
		}

		public static String GetTextBoxValueByName(this IWebDriver driver, String name) {
			IWebElement box = driver.FindElement(By.Name(name));
			if (box == null) {
				throw new ApplicationException(String.Format("No element found with the name '{0}'", name));
			}
			return box.GetAttribute("value");
		}

		public static String GetTextAreaValueByName(this IWebDriver driver, String name) {
			IWebElement area = driver.FindElement(By.Name(name));
			if (area == null) {
				throw new ApplicationException(String.Format("No element found with the name '{0}'", name));
			}
			String value = area.GetAttribute("value");
			return String.IsNullOrWhiteSpace(value) ?
				((IJavaScriptExecutor)driver).ExecuteScript("return arguments[0].innerHTML", area).ToString() :
				value;
		}

		public static String GetTextAreaValueById(this IWebDriver driver, String id) {
			IWebElement area = driver.FindElement(By.Id(id));
			if (area == null) {
				throw new ApplicationException(String.Format("No element found with the id '{0}'", id));
			}
			String value = area.GetAttribute("value");
			return String.IsNullOrWhiteSpace(value) ?
				((IJavaScriptExecutor)driver).ExecuteScript("return arguments[0].innerHTML", area).ToString() :
				value;
		}

		public static void VisitURL(this IWebDriver driver, String relativeURL) {
			driver.Navigate().GoToUrl(String.Format("{0}{1}", TestConfiguration.SiteBaseURL, relativeURL));
		}

		public static void VisitURL(this IWebDriver driver, String relativeURL, String waitForId) {
			driver.VisitURL(relativeURL);

			WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, 10));
			wait.Until(drv => drv.FindElement(By.Id(waitForId)));

			if (driver.PageSource.Contains("Server Error in '/' Application.")) {
				throw new ApplicationException("An error occured on the page " + relativeURL);
			}
		}

		public static IWebElement FindButton(this IWebDriver driver, String text) {
			return driver.FindElement(By.XPath(String.Format("//button[.=\"{0}\"]", text)));
		}

		public static void InsertText(this IWebDriver driver, String name, String text) {
			IWebElement box = driver.FindElement(By.Name(name));
			if (box == null) {
				throw new ApplicationException("No element with that name found");
			}
			driver.InsertText(box, text);
		}

		public static void InsertText(this IWebDriver driver, IWebElement element, String text) {
			element.Clear();
			element.SendKeys(text);

			try {
				IJavaScriptExecutor js = driver as IJavaScriptExecutor;
				js.ExecuteScript("jQuery('#" + element.GetAttribute("id") + "').change();");
			}
			catch { }
		}

		public static void SelectCheckbox(this IWebDriver driver, String name) {
			IWebElement box = driver.FindElement(By.Name(name));
			if (box == null) {
				// TODO:
			}
			if (!box.Selected) {
				box.Click();
			}
		}

		public static void UnselectCheckbox(this IWebDriver driver, String name) {
			// TODO: Sort this!!!! we don't want a try-catch!
			try {
				IWebElement box = driver.FindElement(By.Name(name));
				if (box == null) {
					// TODO:
				}
				if (box.Selected) {
					box.Click();
				}
			}
			catch { }
		}

		public static void SelectOption(this IWebDriver driver, String name, String option) {
			driver.SelectOptions(name, new List<String> { option });
		}

		public static void SelectOption(this IWebDriver driver, ReadOnlyCollection<IWebElement> options,  String selectedText) {
			foreach (IWebElement option in options) {
				if (option.Text == selectedText) {
					option.Click();
					break;
				}
			}
		}

		public static void SelectOptions(this IWebDriver driver, String name, List<String> options) {
			IWebElement dropdown = driver.FindElement(By.Name(name));
			if (dropdown == null) {
				// TODO:
			}
			foreach (IWebElement option in dropdown.FindElements(By.TagName("option"))) {
				if (options.Contains(option.Text)) {
					option.Click();
				}
			}
		}
	}
}